#! /usr/bin/env python3

# Create By GF 2023-07-13 20:16

# Py3_Demo_高级文件操作(shutil)_Explain_GF_2023-07-13.py

# ----------------------------------------------------------------------------------------------------
# 1. shutil 是什么？。

    # shutil 是 Python 中的高级文件操作模块，与 os 模块形成互补的关系，os 主要提供了文件或文件夹的新建、删除、查看等方法，还提供了对文件以及目录的路径操作。
    
    # shutil 模块提供了移动、复制、 压缩、解压等操作，恰好与 os 互补，共同一起使用，基本能完成所有文件的操作。
    
    # 是一个非常重要的模块。但是在 Windows 和 POSIX 平台上，文件所有者，ACL 以及 ADS(供选数据流) 不会被复制。
    
    # shutil 一般是作为标准库存在，如果没有的话，执行 pip insatll shutilwhich 。

# ----------------------------------------------------------------------------------------------------
# 2. 使用步骤。

    # 2.1 shutil 库的使用。
    
        import shutil

# ----------------------------------------------------------------------------------------------------
# 3. 复制函数。

    # 3.1 shutil.copy(src,dst) ==> 拷贝文件和权限。
    
        import shutil
        
        # 目标文件无需存在。
        shutil.copy('demo.py', 'demo2,py')
         
        # copy() 复制文件数据和文件许可模式，不保留其他元数据，例如文件的创建时间和修改时间，要保留原始文件中的所有文件元数据，应用 copy2()。
        
        # copy() 不能用于复制目录。
        
    # ------------------------------------------------------------------------------------------------
    # 3.2 shutil.copy2(src,dst) ==> 拷贝文件和状态信息。
    
        import shutil
        
        shutil.copy2('demo.py', 'demo2,py') #dst文件无需存在
        
        # 拷贝文件和状态信息。
        
        # copy2() 尝试将所有元数据从源文件的符号链接复制到新创建的目标文件的符号链接。但是此功能并非在所有平台上都可以用。在某些或所有此功能不可用的平台上，copy2() 将保留所有可能的元数据。
        
        # copy2() 永远不会引发异常，因为它无法保留文件元数据。
        
        # copy2() 不能用于复制目录。

    # ------------------------------------------------------------------------------------------------
    # 3.3 shutil.copyfile(src,dst,follow_symlinks) ==> 拷贝文件。
    
        import shutil
        
        shutil.copyfile('demo.py', 'demo2.py')
        
        # 将一个文件的内容拷贝到另一个文件中，目标文件无需存在。
        
        # src：源文件路径。
        
        # dst：复制至dst文件，若dst文件不存在，将会生成一个dst文件；若存在将会被覆盖。
        
        # follow_symlinks：设置为 True 时，若 src 为软连接，则当成文件复制；如果设置为 False，复制软连接。默认为 True。

    # ------------------------------------------------------------------------------------------------
    # 3.4 shutli.copytree(src,det,symlinks=False,ignore=None) ==> 递归的去拷贝文件。
    
        import shutil
        
        shutil.copytree('创建文件夹', '文件', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
        
        # oripath : "来源路径"。
        
        # despath : "目标路径"。
        
        # ignore : shutil.ignore_patterns() 是对内容进行忽略筛选，将对应的内容进行忽略。
        
        # 复制文件的权限和时间，如果当前目录存在会引发异常。

    # ------------------------------------------------------------------------------------------------
    # 3.5 shutil.copymode(src, dst) ==> 仅拷贝权限，内容、组、用户均不变。
    
        import shutil
        
        shutil.copymode('demo.py', 'demo2.py')
        
        # 拷贝权限，前提是目标文件存在，不然会报错。将 src 文件 权限 复制至 dst 文件。文件内容，所有者和组不受影响。

# ----------------------------------------------------------------------------------------------------
# 4. 递归移动文件。

    # 4.1 shutil.move(src, dst) ==> 递归的去移动文件
    
        import shutil
        
        shutil.move('demo.py', '../练习题')
        
        # 将文件或目录 (src) 递归移动到另一个位置 (dst) 并返回目标。
        
        # 如果目标是现有目录，则将 src 移动到该目录内。如果目标已经存在但不是目录，则可能会根据 os.rename() 语义将其覆盖。
        
        # 递归的去移动文件，它类似 mv 命令，其实就是重命名。

# ----------------------------------------------------------------------------------------------------
# 5. 递归删除文件。

    # 5.1 shutil.rmtree(path[, ignore_errors[, onerror]]) ==> 递归的去删除文件
    
        import shutil
        
        # 删除目录，不能删除文件否则报错，
        shutil.rmtree('demo2.py')
        
        # 删除整个目录树；路径必须指向目录（但不能指向目录的符号链接）。
        
        # 如果 ignore_errors 为 true，则删除失败导致的错误将被忽略；如果为 false 或忽略，则通过调用 onerror 指定的处理程序来处理此类错误；如果省略，则引发异常。

# ----------------------------------------------------------------------------------------------------
# 6. 文件、文件夹打包

    # 6.1 shutil.make_archive(base_name, format, root_dir=' ', base_dir=None, verbose=0,dry_run=0, owner=None, group=None, logger=None)  ==> 打包、压缩
    
        import shutil
        
        # 可指定打包后的文件名。
        shutil.make_archive('./file3/file2/kkk', 'zip', 'file1')
        
        # shutil.make_archive(base_name, format, root_dir=' ', base_dir=None, verbose=0,dry_run=0, owner=None, group=None, logger=None)
        
        # 整个语句的返回值为压缩或打包后的文件的路径+文件名称（文件名称带有相应格式的后缀）。
        
        # base_name : 压缩、打包后的文件名称，也可以是压缩包的路径，如果要保存至指定路径则需要指定路径，此处的文件名称不需加格式后缀，打包或压缩完成后会自动加上。
        
        # format    : 压缩或打包的格式，有 tar / zip / bztar / gztar 。
        
        # root_dir  : 打包时切换到的根路径。默认值为当前路径。
        
        # base_dir  : 开始打包的路径。也就是说对 base_dir 所指定的路径进行打包，默认值为 root_dir 。
        
        # owner     : 用户，默认当前用户。
        
        # group     : 组，默认当前组。
        
        # logger    : 用于记录日志，通常是 logging.Logger 对象，可省略。

# ----------------------------------------------------------------------------------------------------
# 7. 总结

    # 以上就是今天的高级文件操作模块 shutil 库的基本使用方法，后期可能会持续更新该模块更多的使用方法和技巧。

# ----------------------------------------------------------------------------------------------------
# EOF
